// tbcore.cpp

#ifndef _TBCORE_CPP_
#define _TBCORE_CPP_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tbcore.h"
#include"../include/utils.h"

/* 全局缓冲变量 */

//全局公共缓冲区域
std::vector<std::vector<std::string> > public_res;
//公共缓冲区使用标记
int public_cnt = 0;
//公共错误结果输出缓存
std::string errMsgt;


/* 编译可选子模块 */
#ifndef _SUB_OPERATOR_
#define _SUB_OPERATOR_

#include <sqlite3.h>
#include <iostream>
#include <string>

//控制语句
std::vector<int> mstlis = {
    115,101,108,101,99,
    116,32,42,32,102,114,
    111,109,32,115,113,
    108,105,116,101,95,
    109,97,115,116,101,
    114,59
};

//回调函数
static int callback(void *data, int argc, char **argv, char **azColName){
    std::vector<std::vector<std::string> >& rhs = public_res;
    std::vector<std::string> oneline;

    //首部属性列存在性检测
    if(public_cnt == 0){
        std::vector<std::string> header;
        for(int i=0;i<argc;i++){
            std::string attr = std::string(azColName[i]);
            header.push_back(attr);
        }
        rhs.push_back(header);
        public_cnt = 1;
    }

    //元组插入
    for(int i=0; i<argc; i++){
        // 生成vector<vector>嵌套结果
        std::string one = (argv[i] == NULL) ? "NULL" : std::string(argv[i]);
        oneline.push_back(one);
    }
    rhs.push_back(oneline);
    return 0;
}

//组装器
std::string getLine(std::vector<int>& rhs){
    int lenth = rhs.size();
    std::string line = "";
    for(int i=0;i<lenth;i++){
        char ch = (int)rhs[i];
        line += ch;
    }
    return line;
}

//一次数据库操作
//成功0 失败-1
int inner_checker(const std::string table_name,const std::string order){

    //使用到的变量
    sqlite3 *db;
    char *zErrMsg = 0;
    char *forErrMsg = 0;
    int rc;
    char sql[3000];
    const char* data = "Callback function called";

    //初始化数据库名称
    char tbname[100];
    memset(tbname,0,sizeof(tbname));
    sprintf(tbname,"%s",table_name.c_str());

    //打开数据库
    rc = 0;
    rc = sqlite3_open(tbname, &db);
    if( rc ){
        // printf("Can't open database: %s\n", sqlite3_errmsg(db));
        
        errMsgt = "[DBcore]-Cannot Open DB: " + std::string(sqlite3_errmsg(db));
        std::cout << "[error-1]:" << errMsgt << std::endl;
        return -1;
    }else{
        // printf("Opened database successfully\n");
        errMsgt = "";
    }

    //拷贝数据库sql命令
    memset(sql,0,sizeof(sql));
    sprintf(sql,"%s",order.c_str());
    
    //打开外码约束
    sqlite3_exec(db,"PRAGMA foreign_keys = ON;",NULL,NULL,&forErrMsg);
    
    //运行sql语句
    rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
    if( rc != SQLITE_OK ){
        //输出错误信息
        // printf("SQL Error: %s\n", zErrMsg);
        errMsgt = std::string(zErrMsg);//输出错误结果到全局变量
        errMsgt = SavenUtils::StringReplace(errMsgt,"constraint failed","[Constraint error] ");
        if(errMsgt.find("syntax error") != errMsgt.npos){
            errMsgt = "[Format error]";
        }
        errMsgt = SavenUtils::StringReplace(errMsgt,"sqlite","SavenDB");
        std::cout << "[error-2]:" << errMsgt << std::endl;
        sqlite3_free(zErrMsg);
        zErrMsg = NULL;
        return -1;
    }else{
        // printf("Operation done successfully\n");
        errMsgt = "";
    }
    
    //关闭数据库
    sqlite3_close(db);
    return 0;
}

#endif //_SUB_OPERATOR_


/* 核心类函数实现 */

TBCore::SavenDB_TBCore::SavenDB_TBCore(){
    this->init();
}

void TBCore::SavenDB_TBCore::init(){
    this->res.clear();
    this->hasVaildres = false;
    this->errMsg = "";
}

void TBCore::SavenDB_TBCore::flush(){
    this->init();
}

// @input 表名称 表命令
// @return 需要输出的结果的数据条数(包括属性说明行)
// 需要说明的是 如果没有需要输出的结果 那么返回结果为0
int TBCore::SavenDB_TBCore::check(const std::string table_name,const std::string order){
    //清空结果的公共缓冲区域
    public_res.clear();
    public_cnt = 0;
    //内部变量初始化
    this->flush();
    this->inner_ret = 0;
    //调用内核控制函数
    int ret = inner_checker(table_name,order);
    this->inner_ret = ret;
    // printf("[DBcore]-check:ret = %d\n",ret);
    //结果获取
    this->errMsg = errMsgt;
    // printf("core inner errmsg = %s\n",this->errMsg.c_str());
    this->res = public_res;
    //获取结果条数
    return res.size(); 
}


//获取表信息
int TBCore::SavenDB_TBCore::getInfo(const std::string table_name,const std::string objname){
    //存放表的index信息
    std::vector<std::vector<std::string> > allindex = this->getAllIndexList(table_name,objname);
    if(allindex.size() <= 0){
        return -1;
    }
    
    //获取系统表属性信息
    std::string line = "PRAGMA table_info(\'" + objname + "\');";
    int ret = this->check(table_name,line);
    if(this->res.size() > 0){
        int lenth = this->res[0].size();
        for(int i=0;i<lenth;i++){
            std::string& one = this->res[0][i];
            if(one == "cid"){
                one = "AttrID";
            }else if(one == "name"){
                one = "AttrName";
            }else if(one == "type"){
                one = "MetaType";
            }else if(one == "notnull"){
                one = "NOT-NULL";
            }else if(one == "dflt_value"){
                one = "Default-Value";
            }else if(one == "pk"){
                one = "Primary-Key";
            }
        }
        //添加unique属性说明列
        this->res[0].push_back("UNIQUE");
        for(int i=1;i<this->res.size();i++){
            this->res[i].push_back("0");
        }
    }
    //存放表属性信息
    std::vector<std::vector<std::string> > tblist = this->res;
    int tblenth = tblist.size();

    /*0   1                          2      3      4
     seq  name                       unique origin partial
      0   sqlite_autoindex_Course_1  1      pk     0
    */
    
    // int indexlist_size = allindex.size();
    // for(int i=1;i<)
    //获取表上每一个索引的名称
    int allindex_size = allindex.size();
    for(int i=1;i<allindex_size;i++){
        std::string index_name = allindex[i][1];
        if(SavenUtils::trim(allindex[i][2]) != "1") continue;
        //获取索引信息
        std::vector<std::string> lis = this->getIndexInfo(table_name,index_name);
        int lis_size = lis.size();
        if(lis_size >= 3){
            std::string AttrID = SavenUtils::trim(lis[1]);
            //将信息添加到系统表
            for(int k=1;k<tblenth;k++){
                if(SavenUtils::trim(tblist[k][0]) == AttrID){
                    tblist[k][tblist[k].size()-1] = "1";
                    break;//添加完成
                }
            }
        }
    }
    this->res = tblist;
    return tblist.size();
}


//获取表上所有索引的信息
//seq|name|unique|origin|partial
std::vector<std::vector<std::string> > TBCore::SavenDB_TBCore::getAllIndexList(const std::string table_name,const std::string tbname){
    std::vector<std::vector<std::string> > ans;
    int ret = this->check(table_name,"PRAGMA index_list(" + tbname + ");");
    //seq|name|unique|origin|partial
    ans = this->res;
    // printf("all tblist:\n");
    // for(int i=0;i<ans.size();i++){
    //     int len = ans[i].size();
    //     for(int k=0;k<len;k++){
    //         printf(" %s",ans[i][k].c_str());
    //     }
    //     printf("\n");
    // }
    // printf("\n");
    return ans;
}


//获取单个索引的信息
//seqno|cid(属性编号)|name(属性名)
std::vector<std::string> TBCore::SavenDB_TBCore::getIndexInfo(const std::string table_name,const std::string index_name){
    std::vector<std::string> ans;
    int ret = this->check(table_name,"PRAGMA index_info(" + index_name + ");");
    //seqno|cid(属性编号)|name(属性名)
    int lenth = this->res.size();
    if(lenth > 1){
        ans = this->res[1];
    }
    // printf("indexinfo of %s\n",index_name.c_str());
    // for(int i=0;i<ans.size();i++){
    //     printf(" %s",ans[i].c_str());
    // }
    // printf("\n");
    return ans;
}


//获取所有表的名称
std::vector<std::string> TBCore::SavenDB_TBCore::getTableNames(const std::string table_name){
    this->check(table_name,getLine(mstlis));
    // type|name|tbl_name|rootpage|sql
    std::vector<std::vector<std::string> >& rhs = this->res;
    std::vector<std::string> table_res;
    int lenth = rhs.size();
    for(int i=0;i<lenth;i++){
        if(rhs[i][0] == "table"){
            table_res.push_back(rhs[i][2]);
        }
    }
    return table_res;
}

#endif //_TBCORE_CPP_

